import Taro from '@tarojs/taro'
import LogService from "./LogService";
import DeviceConfig from "../config/DeviceConfig";
import {BuffUtils} from "../utils/BuffUtils";
import MessageConfig from "../config/MessageConfig";
import EventUtils from "../utils/EventUtils";

Taro.onBLEConnectionStateChange(function (res) {
  // 该方法回调中可以用于处理连接意外断开等异常情况
  const {deviceId, connected} = res;
  LogService.info(`device ${deviceId} state has changed, connected: ${connected}`);
  BluDeviceComService.connected = connected;
  BluDeviceComService.deviceId = deviceId;
  if (!connected)
    EventUtils.trigger(MessageConfig.BlE_CONNECT_TYPE, res)
});

export default class BluDeviceComService {

  static connected = false;

  static async connetBlue(deviceId) {
    this.disconnetBlue(deviceId);

    try {
      const res = await Taro.createBLEConnection({
        deviceId,
      });
      LogService.debug("createBLEConnection success", res);
      await BluDeviceComService.getBLEDeviceServices(deviceId);
      BluDeviceComService.lisBluData(deviceId);
      EventUtils.trigger(MessageConfig.BlE_CONNECT_TYPE, {deviceId, connected: true});
    } catch (e) {
      LogService.error("createBLEConnection fail", e)
    }
  }

  static async disconnetBlue() {

    if (!BluDeviceComService.deviceId)
      return;
    let deviceId = BluDeviceComService.deviceId;
    try {
      const res = await Taro.closeBLEConnection({
        deviceId,
      });
      LogService.debug("closeBLEConnection success", deviceId, res);
    } catch (e) {
      LogService.error("closeBLEConnection fail", deviceId, e);
    }

    BluDeviceComService.deviceId = undefined;
  }

  /**
   * 获取服务名称和特征uuid
   * @param deviceId
   */
  static async getBLEDeviceServices(deviceId) {
    try {
      const res = await Taro.getBLEDeviceServices({
        // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
        deviceId
      });
      LogService.debug("getBLEDeviceServices sucess", deviceId, res);
      for (let i = 0; i < res.services.length; i++) {
        let value = res.services[i];
        const {uuid} = value;
        await BluDeviceComService.getCharacteristics(deviceId, uuid);
      }
    } catch (e) {
      LogService.error("getBLEDeviceServices fail", deviceId, e);
    }
  }

  static async getCharacteristics(deviceId, uuid) {
    try {
      const res = await Taro.getBLEDeviceCharacteristics({
        // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
        deviceId,
        // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
        serviceId: uuid,
      });
      LogService.debug('device getBLEDeviceCharacteristics sucess:', res.characteristics)
    } catch (e) {
      LogService.error('device getBLEDeviceCharacteristics fail:', e);
    }
  }

  /**
   * 监听接收数据
   * @param deviceId
   */
  static lisBluData(deviceId) {
    Taro.notifyBLECharacteristicValueChange({
      state: true, // 启用 notify 功能
      // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      deviceId,
      // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
      serviceId: DeviceConfig.Service_UUID,
      // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
      characteristicId: DeviceConfig.NOTIFY_UUID,
      success: function (res1) {
        LogService.debug("notifyBLECharacteristicValueChange success", res1);

        // 监听设备发过来的数据
        Taro.onBLECharacteristicValueChange(function (res) {
          const {characteristicId, value} = res;
          let data = BuffUtils.buffToArr(value);
          LogService.debug("onBLECharacteristicValueChange:", characteristicId, value, data);
          EventUtils.trigger(MessageConfig.BlE_RECV_TYPE, {data, sucess: true, deviceId})
        })
      },
      fail: function (res) {
        LogService.error("notifyBLECharacteristicValueChange fail", res)
      }
    })
  }

  static readData(deviceId, characteristicId) {
    Taro.readBLECharacteristicValue({
      // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      deviceId,
      // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
      serviceId: DeviceConfig.Service_UUID,
      // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
      characteristicId,
      success: function (res) {
        LogService.debug('readBLECharacteristicValue:', res)
      }
    })
  }

  /**
   * 向蓝牙设备发送一个0x00的16进制数据
   * let buffer = new ArrayBuffer(1)
   * @param deviceId
   * @param arr
   */
  static sendData(deviceId, arr) {
    let buffer = BuffUtils.arrToBuffer(arr);

    Taro.writeBLECharacteristicValue({
      // 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
      deviceId,
      // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
      serviceId: DeviceConfig.Service_UUID,
      // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
      characteristicId: DeviceConfig.WRITE_NO_ESPONSE_UUID,
      // 这里的value是ArrayBuffer类型
      value: buffer,
      success: function (res) {
        LogService.debug('writeBLECharacteristicValue success', res);
        EventUtils.trigger(MessageConfig.BlE_SEND_TYPE, {data: arr, sucess: true, deviceId})
      },
      fail: function (res) {
        LogService.error('writeBLECharacteristicValue fail', res);
        EventUtils.trigger(MessageConfig.BlE_SEND_TYPE, {data: arr, sucess: false, deviceId})
      }
    })
  }
}
